﻿using Bomber.TF.GameCenter.BlockCenter;
using Bomber.TF.GameCenter.BomberCenter;
using Bomber.TF.GameCenter.ToolCenter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bomber.TF.GameCenter.BombCenter
{
    public unsafe abstract class BombBase : GameBase
    {
        protected readonly BomberBase _bomber;
        public BombBase(SpeciesType speciesType, Size size, BomberBase bomberBase) : base(speciesType, size)
        {
            _bomber = bomberBase;
        }
        public Action<BombBase>? BlastCallback;
        // 2所有方向  0水平  1垂直
        private byte _directionBomb = 2;
        protected virtual void Attack(GameListBase* ptr)
        {
            // 中心
            AttackCenter(ptr);
            // 上
            AttackUp(ptr);
            // 下
            AttackDown(ptr);
            // 左
            AttackLeft(ptr);
            // 右
            AttackRight(ptr);
        }
        protected virtual void AttackCenter(GameListBase* ptr)
        {
            GameListBase* p = ptr + base.Row * base.MaxColumn + base.Column;
            AttackBomber(p);
        }
        protected virtual void AttackUp(GameListBase* ptr)
        {
            int row = base.Row - 1;
            if (row < 1) return;
            GameListBase* up = ptr + row * base.MaxColumn + base.Column;
            if (up->Games.Count == 0 || _directionBomb == 0) return;
            if (_directionBomb == 2)
                AttackBomber(up);
            AttackDestroyBlock(up);
        }
        protected virtual void AttackDown(GameListBase* ptr)
        {
            int row = base.Row + 1;
            if (row > base.MaxRow - 2) return;
            GameListBase* down = ptr + row * base.MaxColumn + base.Column;
            if (down->Games.Count == 0 || _directionBomb == 0) return;
            if (_directionBomb == 2)
                AttackBomber(down);
            AttackDestroyBlock(down);
        }
        protected virtual void AttackLeft(GameListBase* ptr)
        {
            int col = base.Column - 1;
            if (col < 1) return;
            GameListBase* left = ptr + base.Row * base.MaxColumn + col;
            if (left->Games.Count == 0 || this._directionBomb == 1) return;
            if (_directionBomb == 2)
                AttackBomber(left);
            AttackDestroyBlock(left);
        }
        protected virtual void AttackRight(GameListBase* ptr)
        {
            int col = base.Column + 1;
            if (col > base.MaxColumn - 2) return;
            GameListBase* right = ptr + base.Row * base.MaxColumn + col;
            if (right->Games.Count == 0 || this._directionBomb == 1) return;
            if (_directionBomb == 2)
                AttackBomber(right);
            AttackDestroyBlock(right);
        }
        protected void AttackDestroyBlock(GameListBase* ptr)
        {
            var first = ptr->Games.FirstOrDefault(t => t.SpeciesType == SpeciesType.DestroyBlock);
            if (first == null) return;
            ptr->Games.Clear();
            // 添加道具
            DestroyBlock? destroyBlock = first as DestroyBlock;
            if (destroyBlock.ToolType == SpeciesType.None) return;
            var tool = destroyBlock.ToolType.CreateTool(first);
            if (tool == null) return;
            ptr->Games.Add(tool);
        }
        protected virtual void AttackBomber(GameListBase* ptr)
        {
            for (int i = 0; i < ptr->Games.Count; i++)
            {
                var game = ptr->Games[i];
                if (!game.IsBomber) continue;
                // 炸弹人被炸弹攻击
                BomberBase? bomber = game as BomberBase;
                bomber?.Attacked();
            }
        }
        /// <summary>
        /// 炸弹爆炸
        /// </summary>
        /// <param name="bombBase"></param>
        protected virtual void CreateBomb(GameListBase* ptr)
        {
            BlastCallback?.Invoke(this);
            if (_bomber.BombRange == 1) return;

            int count = _bomber.BombRange - 1;
            int k = 1;
            bool right = true, left = true, top = true, down = true;
            for (int i = 0; i < _bomber.BombRange - 1; i++)
            {
                if (right)
                    RightBomb(ptr, ref right, ref count, k);
                if (count <= 0) break;
                if (left)
                    LeftBomb(ptr, ref left, ref count, k);
                if (count <= 0 || (!right && !left)) break;
                k++;
            }
            k = 1;
            count = _bomber.BombRange - 1;
            for (int i = 0; i < _bomber.BombRange - 1; i++)
            {
                if (down)
                    DownBomb(ptr, ref down, ref count, k);
                if (count <= 0) break;
                if (top)
                    TopBomb(ptr, ref top, ref count, k);
                if (count <= 0 || (!top && !down)) break;
                k++;
            }
        }
        private void TopBomb(GameListBase* ptr, ref bool status, ref int count, int k)
        {
            int row = this.Row - k;
            if (row < 1)
                status = false;
            else
                VerticalBomb(ptr, row, ref status, ref count);
        }
        private void DownBomb(GameListBase* ptr, ref bool status, ref int count, int k)
        {
            int row = this.Row + k;
            if (row > base.MaxRow - 2)
                status = false;
            else
                VerticalBomb(ptr, row, ref status, ref count);
        }
        private void LeftBomb(GameListBase* ptr, ref bool status, ref int count, int k)
        {
            int col = this.Column - k;
            if (col < 1)
                status = false;
            else
                HorizontalBomb(ptr, col, ref status, ref count);
        }
        private void RightBomb(GameListBase* ptr, ref bool status, ref int count, int k)
        {
            int col = this.Column + k;
            if (col > this.MaxColumn - 2)
                status = false;
            else
                HorizontalBomb(ptr, col, ref status, ref count);
        }
        private void HorizontalBomb(GameListBase* ptr, int col, ref bool status, ref int count) => DirectionBomb(ptr, base.Row, col, 0, ref status, ref count);
        private void VerticalBomb(GameListBase* ptr, int row, ref bool status, ref int count) => DirectionBomb(ptr, row, base.Column, 1, ref status, ref count);
        private void DirectionBomb(GameListBase* ptr, int row, int col, byte directionBomb, ref bool status, ref int count)
        {
            GameListBase* p = ptr + row * this.MaxColumn + col;
            if (p->Games.Any(t => t.IsBlock))
                status = false;
            else
            {
                var bomb = (BombBase)this.Clone();
                bomb.Row = row;
                bomb.Column = col;
                bomb._directionBomb = directionBomb;
                bomb.UpdateLocation();
                p->Games.Add(bomb);
                --count;
            }
        }
    }
}
